package dicttypelogic

import (
	"context"

	"go-zero-admin/apps/system/cmd/rpc/internal/logic/dictdata"
	"go-zero-admin/apps/system/cmd/rpc/internal/svc"
	"go-zero-admin/apps/system/cmd/rpc/syspb"
	"go-zero-admin/apps/system/model"
	"go-zero-admin/pkg/tool"
	"go-zero-admin/pkg/xerr"

	"github.com/pkg/errors"
	"github.com/zeromicro/go-zero/core/fx"
	"github.com/zeromicro/go-zero/core/logx"
	"github.com/zeromicro/go-zero/core/mr"
	"github.com/zeromicro/go-zero/core/stores/sqlx"
)

type DelDictTypeLogic struct {
	ctx    context.Context
	svcCtx *svc.ServiceContext
	logx.Logger
	getDictDataListLogic *dictdatalogic.GetDictDataListLogic
}

func NewDelDictTypeLogic(ctx context.Context, svcCtx *svc.ServiceContext) *DelDictTypeLogic {
	return &DelDictTypeLogic{
		ctx:                  ctx,
		svcCtx:               svcCtx,
		Logger:               logx.WithContext(ctx),
		getDictDataListLogic: dictdatalogic.NewGetDictDataListLogic(ctx, svcCtx),
	}
}

func (l *DelDictTypeLogic) DelDictType(in *syspb.DelDictTypeReq) (*syspb.DelDictTypeResp, error) {
	if len(in.GetIds()) == 0 || (!in.GetIsDel() && in.GetUpdateUser() == "") {
		return nil, errors.Wrapf(xerr.NewErrMsg("删除字典类型失败：参数缺失"),
			tool.GetErrMsgFormat("delete dictType"), "params is not existed", in)
	}

	// 获取字典类型列表
	dictTypeList, err := mr.MapReduce(func(source chan<- interface{}) {
		for _, v := range in.GetIds() {
			source <- v
		}
	}, func(item interface{}, writer mr.Writer, cancel func(error)) {
		one, e := l.svcCtx.SysDictTypeModel.FindOne(l.ctx, item.(int64))
		if e != nil {
			cancel(e)
			return
		}
		writer.Write(one.DictType)
	}, func(pipe <-chan interface{}, writer mr.Writer, cancel func(error)) {
		var dictTypeList []string
		for p := range pipe {
			dictTypeList = append(dictTypeList, p.(string))
		}
		writer.Write(dictTypeList)
	})
	if err != nil {
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.DbError),
			tool.GetErrMsgFormat("delete dictType"), err, in)
	}
	if dictTypeList == nil || len(dictTypeList.([]string)) != len(in.GetIds()) {
		return nil, errors.Wrapf(xerr.NewErrMsg("删除字典类型失败：获取字典类型数据错误"),
			tool.GetErrMsgFormat("delete dictType"), err, in)
	}

	// 获取所有字典类型下数据
	dictDataListResp, err := l.getDictDataListLogic.GetDictDataList(&syspb.GetDictDataListReq{
		DictTypeList: dictTypeList.([]string),
	})
	if err != nil {
		return nil, err
	}
	dictDataList := dictDataListResp.GetList()

	// 如果字典下无数据就只删除字典类型数据
	if len(dictDataList) == 0 {
		err = l.svcCtx.SysDictTypeModel.DeleteEx(l.ctx, nil, in.GetIds(), in.GetIsDel(), in.GetUpdateUser())
		if err != nil {
			return nil, errors.Wrapf(xerr.NewErrFindOneCode(err, model.ErrNotFound),
				tool.GetErrMsgFormat("delete dictType"), err, in)
		}
		return &syspb.DelDictTypeResp{}, nil
	}

	// 获取所有字典类型下数据Id
	dictDataIdList := make([]int64, 0)
	fx.From(func(source chan<- interface{}) {
		for _, v := range dictDataList {
			source <- v
		}
	}).Map(func(item interface{}) interface{} {
		return item.(*syspb.SysDictData).GetDictCode()
	}).ForEach(func(item interface{}) {
		dictDataIdList = append(dictDataIdList, item.(int64))
	})

	// 删除数据
	if err = l.svcCtx.SysDictTypeModel.Trans(l.ctx, func(context context.Context, session sqlx.Session) error {
		var e error
		e = l.svcCtx.SysDictDataModel.DeleteEx(l.ctx, session, dictDataIdList, in.GetIsDel(), in.GetUpdateUser())
		if e != nil {
			return e
		}

		e = l.svcCtx.SysDictTypeModel.DeleteEx(l.ctx, session, in.GetIds(), in.GetIsDel(), in.GetUpdateUser())
		if e != nil {
			return e
		}

		return nil
	}); err != nil {
		return nil, errors.Wrapf(xerr.NewErrFindOneCode(err, model.ErrNotFound),
			tool.GetErrMsgFormat("delete dictType"), err, in)
	}

	return &syspb.DelDictTypeResp{}, nil
}
